package org.bkhech.mybatis.extend.generator.plugins;

import org.bkhech.mybatis.extend.generator.constant.GeneratorConstant;
import org.bkhech.mybatis.extend.generator.util.GeneratorUtil;
import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.exception.ShellException;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.mybatis.generator.internal.util.StringUtility;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 生成继承自GenericMapper的Mapper接口
 *
 * Created by guowm on 2017/2/13.
 */
public class GenericServiceGeneratorPlugin extends PluginAdapter {

    private String serviceTargetDir;
    private String serviceTargetPackage;

    private ShellCallback shellCallback = null;

    public GenericServiceGeneratorPlugin() {
        this.shellCallback = new DefaultShellCallback(false);
    }

    @Override
    public boolean validate(List<String> list) {
        String serviceTargetDir = this.properties.getProperty("serviceTargetDir");
        this.serviceTargetDir = serviceTargetDir;
        String serviceTargetPackage = this.properties.getProperty("serviceTargetPackage");
        this.serviceTargetPackage = serviceTargetPackage;
        return StringUtility.stringHasValue(serviceTargetDir) && StringUtility.stringHasValue(serviceTargetPackage);
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        ArrayList<GeneratedJavaFile> mapperJavaFiles = new ArrayList<GeneratedJavaFile>();
        JavaFormatter javaFormatter = this.context.getJavaFormatter();

        List<IntrospectedColumn> primaryKeyColumns = introspectedTable.getPrimaryKeyColumns();

        String packageName = introspectedTable.getFullyQualifiedTable().getSubPackage(true);

        Iterator<GeneratedJavaFile> javaFilesIterator = introspectedTable.getGeneratedJavaFiles().iterator();
        while (javaFilesIterator.hasNext()) {
            GeneratedJavaFile javaFile = javaFilesIterator.next();
            CompilationUnit unit = javaFile.getCompilationUnit();
            FullyQualifiedJavaType modelJavaType = unit.getType();
            String shortName = modelJavaType.getShortName();
            if(shortName.equals(introspectedTable.getFullyQualifiedTable().getDomainObjectName()) &&
                    !shortName.endsWith("Example") && !shortName.endsWith("Mapper") && !shortName.endsWith("SqlProvider")) {
                String serviceName = shortName + "Service";
                Interface serviceInterface = new Interface(this.serviceTargetPackage + packageName + "." + serviceName);
                serviceInterface.setVisibility(JavaVisibility.PUBLIC);

                serviceInterface.addJavaDocLine("/**");
                serviceInterface.addJavaDocLine(" * Service: " + serviceName);
                serviceInterface.addJavaDocLine(" * Mapper : " + shortName + "Mapper");
                serviceInterface.addJavaDocLine(" * Model  : " + shortName);
                serviceInterface.addJavaDocLine(" *");
                serviceInterface.addJavaDocLine(" * This Service generated by MyBatis Generator Extend at " + GeneratorUtil.now());
                serviceInterface.addJavaDocLine(" */");

                serviceInterface.addImportedType(modelJavaType);

                if (primaryKeyColumns.size() > 0) {
                    FullyQualifiedJavaType pkType = primaryKeyColumns.size() > 1
                            ? unit.getSuperClass() : primaryKeyColumns.get(0).getFullyQualifiedJavaType();

                    FullyQualifiedJavaType superInterfaceType = new FullyQualifiedJavaType(GeneratorConstant.GENERIC_SERVICE_CLASS_PATH);
                    serviceInterface.addImportedType(superInterfaceType);
                    superInterfaceType.addTypeArgument(modelJavaType);
                    superInterfaceType.addTypeArgument(pkType);
                    serviceInterface.addSuperInterface(superInterfaceType);
                } else {
                    FullyQualifiedJavaType superInterfaceType = new FullyQualifiedJavaType(GeneratorConstant.GENERIC_WITHOUT_PRIMARY_KEY_SERVICE_CLASS_PATH);
                    serviceInterface.addImportedType(superInterfaceType);
                    superInterfaceType.addTypeArgument(modelJavaType);
                    serviceInterface.addSuperInterface(superInterfaceType);
                }

                try {
                    GeneratedJavaFile file = new GeneratedJavaFile(serviceInterface, this.serviceTargetDir, javaFormatter);
                    File mapperDir = this.shellCallback.getDirectory(this.serviceTargetDir, this.serviceTargetPackage + packageName);
                    File mapperFile = new File(mapperDir, file.getFileName());
                    if(!mapperFile.exists()) {
                        mapperJavaFiles.add(file);
                    }
                } catch (ShellException e) {
                    e.printStackTrace();
                }
            }
        }
        return mapperJavaFiles;
    }

}
